﻿using System;
using System.Collections.Generic;
using MugenInjection.Interception.Syntax;
using MugenInjection.Interface;
using MugenInjection.Interface.Components;
using MugenInjection.Syntax;

namespace MugenInjection.Interception.Interface.Components
{
    /// <summary>
    /// Represents the component that manages IInterceptors.
    /// </summary>
    public interface IInterceptionManagerComponent : IComponent
    {
        /// <summary>
        /// Gets the <see cref="IProxyFactory"/>.
        /// </summary>
        IProxyFactory ProxyFactory { get; }

        /// <summary>
        /// Gets all <see cref="IInterceptorProcess"/> for specified <see cref="IBinding"/>.
        /// </summary>
        /// <param name="binding">The specified <see cref="IBinding"/>.</param>
        /// <returns>Found <see cref="IList{IInterceptorProcess}"/>.</returns>
        IList<IInterceptorProcess> GetInterceptorProcesses(IBinding binding);

        /// <summary>
        /// Adds the specified <see cref="IInterceptorProcess"/> for specified <see cref="IBinding"/>.
        /// </summary>
        /// <param name="binding">The specified <see cref="IBinding"/>.</param>
        /// <param name="interceptorProcess">The specified <see cref="IInterceptorProcess"/>.</param>
        void AddInterceptorProcess(IBinding binding, IInterceptorProcess interceptorProcess);

        /// <summary>
        /// Adds the specified <see cref="ISimpleInterceptorProcess"/> for specified <see cref="IBinding"/>.
        /// </summary>
        /// <param name="binding">The specified <see cref="IBinding"/>.</param>
        /// <param name="simpleInterceptorProcess">The specified <see cref="ISimpleInterceptorProcess"/>.</param>
        void AddInterceptorProcess(IBinding binding, ISimpleInterceptorProcess simpleInterceptorProcess);

        /// <summary>
        /// Indicates that instances associated with this binding will be proxied.
        /// </summary>
        /// <param name="bindingSyntax">The binding syntax target.</param>
        /// <param name="interfaces">The specified interfaces for proxy.</param>
        /// <param name="interceptorProcesses">The specified <see cref="IInterceptorProcess"/> for intercept.</param>
        /// <returns>The fluent syntax.</returns>
        IInterceptTypeSyntax Intercept(ICommonBindingSyntax bindingSyntax, Type[] interfaces, IInterceptorProcess[] interceptorProcesses);

        /// <summary>
        /// Indicates that instances associated with this binding will be proxied.
        /// </summary>
        /// <param name="genericBindingSyntax">The binding syntax target.</param>
        /// <param name="interfaces">The specified interfaces for proxy.</param>
        /// <param name="interceptorProcesses">The specified <see cref="IInterceptorProcess"/> for intercept.</param>
        /// <returns>The fluent syntax.</returns>
        IInterceptTypeSyntax<T> Intercept<T>(IGenericBindingSyntax<T> genericBindingSyntax, Type[] interfaces, IInterceptorProcess[] interceptorProcesses);

        /// <summary>
        /// Indicates that instances associated with this binding will be proxied and the target will be to the original binding.
        /// </summary>
        /// <param name="bindingBuilder">The binding builder for target.</param>
        /// <param name="interfaces">Interfaces for proxy.</param>
        /// <param name="alwaysNewProxy">Always create a new proxy object, regardless of the target.</param>
        /// <param name="interceptorProcesses">The specified <see cref="IInterceptorProcess"/> for intercept.</param>
        TSyntaxType InterceptAsTarget<TSyntaxType>(IBindingBuilder bindingBuilder, Type[] interfaces, bool alwaysNewProxy, IInterceptorProcess[] interceptorProcesses);

        /// <summary>
        /// Indicates that instances associated with this binding will be proxied and the target will be to the original binding.
        /// </summary>
        /// <param name="bindingBuilder">The binding builder for target.</param>
        /// <param name="interfaces">Interfaces for proxy.</param>
        /// <param name="alwaysNewProxy">Always create a new proxy object, regardless of the target.</param>
        /// <param name="interceptorProcesses">The specified <see cref="IInterceptorProcess"/> for intercept.</param>
        TSyntaxType InterceptAsTarget<TType, TSyntaxType>(IBindingBuilder bindingBuilder, Type[] interfaces, bool alwaysNewProxy, IInterceptorProcess[] interceptorProcesses);

        /// <summary>
        /// Creates an <see cref="IInterceptor"/> for intercept all processes.
        /// </summary>
        /// <param name="proxy">The specified <see cref="IProxy"/>. </param>
        /// <param name="interceptorProcesses">The specified <see cref="IInterceptorProcess"/> for intercept proxy.</param>
        /// <returns>An instance of the <see cref="IInterceptor"/>.</returns>
        IInterceptor CreateInterceptor(IProxy proxy, IList<IInterceptorProcess> interceptorProcesses);
    }
}